#include <QSqlQuery>
#include <QSqlError>
#include <QSqlRecord>
#include <QVariant>
#include <QDebug>
#include "getrequestprocess.h"
#include "macro.h"

GetRequestProcess::GetRequestProcess(QSqlQuery *parentQury,QObject *parent) :
    QObject(parent)
{
    qury= new QSqlQuery(QSqlDatabase::database(DB_Con_Name_ClientDataProcess));
}

/*
  该函数先把字符串内容全部转为大写，然后处理
  */
QByteArray GetRequestProcess::analyzeGetDatagram(QByteArray &datagram)
{
    QByteArray reply,uri;
    reply.append("DATA:"+datagram+"\n");

    QList <QByteArray> listData=datagram.simplified().split(' ');
    if(listData.size()!=2)
        reply.append("ERROR: Param not correct. Number of space not supposed.");
    else
    {
        dataGramProcessing=datagram;
        uri=listData.at(1);
        uri=QString::fromUtf8(uri).toUpper().toUtf8(); //全部转为大写.
        if(uri=="ALIVENODESENSORS")
            reply.append(getAliveNodeSensors(uri));
        else if(uri=="ALLNODESENSORS")
            reply.append(getAllNodeSensors(uri));
        else
        {
            QList <QByteArray> listURIItems=uri.split('/');
            if(listURIItems.size()<2)
                reply.append("ERROR:'/' missing.");
            else
            {
                if(listURIItems.at(0)=="INFO")
                    reply.append(getInfo(listURIItems));
                else if(listURIItems.at(1)=="NODEMAC")
                    reply.append(getNodeMac(listURIItems));
                else if(listURIItems.at(1)=="REALTIMEDATA")
                    reply.append(getRealTimeData(listURIItems));
                else if(listURIItems.at(1)=="HISTORYDATA")
                    reply.append(getHistoryData(listURIItems));
                else if(listURIItems.at(1)=="STATE")
                    reply.append(getState(listURIItems));
                else
                    reply.append("ERROR: Resource not found maching the URI.");
            }
        }
    }
    return reply;
}

QByteArray GetRequestProcess::getNodeMac(QList<QByteArray> &listUriItems)
{
    QByteArray reply;


    if(listUriItems.size()!=2)
        reply="ERROR:URI is not correct.There should be 1 '/'";
    else
    {
        QSqlQuery tempQuery(QSqlDatabase::database(DB_Con_Name_ClientDataProcess));

        QByteArray nodeName=listUriItems.at(0);
        if(tempQuery.exec("select NodeName,NodeMacAddress from "
                      "NodeAddressMap where nodename like '"+nodeName+"'"))
        {
            if(!tempQuery.next())
                reply="ERROR:No Node is matched.\n";
            else
            {
              bool ok;
              QByteArray  nodeNameExact=tempQuery.value(0).toString().toUtf8();
              quint64 nodeMac=tempQuery.value(1).toLongLong(&ok);
              reply="NodeName:"+nodeNameExact+"\n"
                           "NodeMac:"+QByteArray::number(nodeMac)+"\n"
                           "Content_Type:UTF8 String\n";
              if(tempQuery.next()) //如果不止一条结果，则报错
                  reply="ERROR:Ambiguity in node name. Multiple nodes are matched.";
              else
                  reply.prepend("DATA_Type:NodeMAC\n");


            }

        }
    }
    return reply;
}

QByteArray GetRequestProcess::getAllNodeSensors(QByteArray &uri)
{
    QByteArray reply,strSQL;
    strSQL="SELECT NodeName,NodeMacAddress,SensorName,NodeOnWork,SensorOnWork FROM nodesensorview";

    QSqlQuery tempQuery(QSqlDatabase::database(DB_Con_Name_ClientDataProcess));

    if(tempQuery.exec(strSQL))  //如果数据库操作成功
    {
       quint8 columnCount=tempQuery.record().count();
       while(tempQuery.next())
       {
            for(int n=0;; n++)
           {
              reply.append(tempQuery.value(n).toString().toUtf8()); //统一UTF8编码
                if(n<columnCount-1)
                    reply.append('\t');
                else break;
           }
            reply.append('\n');
            if(reply.size()>=UDP_MAX_Bytes)
                break;
       }//while结束
     }   // if(tempQuery.exec(strSQL))  结束
    else //如果操作数据库有误
    {
        reply="ERROR: DATABASE ERROR.\n";
        reply.append(tempQuery.lastError().text().toLatin1());
    }

    if(reply.size()<=UDP_MAX_Bytes)
        return reply;
    else
        return reply.mid(0,UDP_MAX_Bytes);
}


QByteArray GetRequestProcess::getAliveNodeSensors(QByteArray &uri)
{
    QByteArray reply,strSQL;
    strSQL="SELECT NodeName,NodeMacAddress,SensorName,SensorOnWork FROM nodesensorview where nodeonwork=1;";
    QSqlQuery tempQuery(QSqlDatabase::database(DB_Con_Name_ClientDataProcess));

    if(tempQuery.exec(strSQL))  //如果数据库操作成功
    {
        quint8 columnCount=tempQuery.record().count();
       while(tempQuery.next())
       {
            for(int n=0;; n++)
           {
              reply.append(tempQuery.value(n).toString().toUtf8()); //统一UTF8编码
                if(n<columnCount-1)
                    reply.append('\t');
                else break;
           }
            reply.append('\n');
            if(reply.size()>=UDP_MAX_Bytes)
                break;
       }//while结束
     }   // if(tempQuery.exec(strSQL))  结束
    else //如果操作数据库有误
    {
        reply.append("ERROR: DATABASE ERROR.");
        reply.append(tempQuery.lastError().text().toLatin1());
    }

    if(reply.size()<=UDP_MAX_Bytes)
        return reply;
    else
        return reply.mid(0,UDP_MAX_Bytes);
}

/*
  注：URI中的内容已经全部转为了大写.到数据库中进行字符串匹配查询时，也需要把数据库中字符串转为大写
  */
QByteArray GetRequestProcess::getRealTimeData(QList<QByteArray> &listUriItems)
{
    QByteArray reply;
    QSqlQuery tempQuery(QSqlDatabase::database(DB_Con_Name_ClientDataProcess));

    if(listUriItems.size()!=3)
        reply.append("ERROR:URI is not correct.There should be 2 '/'");
    else
    {
        QByteArray nodeName,strQuery;
        nodeName=listUriItems.at(0);
        strQuery=listUriItems.at(2);
        if(!strQuery.contains("SENSORNAME="))
            reply.append("ERROR:URI not correct.It should contain 'SensorName='");
        else
        {
            QByteArray temp="SENSORNAME=";
            qint16 index=strQuery.indexOf(temp);
            QList <QByteArray> listSensorName=strQuery.mid(index+temp.size()).split('+');
            quint8 sensorNum=listSensorName.size();            
            QByteArray strSQL;

            for(int indexOfSensor=0;indexOfSensor<sensorNum;indexOfSensor++)
            {
                strSQL="select datetime,tm.sensorname,SensorData from rToday, TypeMap tm where  "
                        "NodeMacAddress in (select NodeMacAddress from NodeAddressmap where NodeName like '"+nodeName+"') and "
                        " tm.SensorName='"+listSensorName.at(indexOfSensor)+"' and rToday.SensorID=tm.SensorID order by id desc limit 1";
                if(tempQuery.exec(strSQL))  //如果数据库操作成功
                {
                    quint8 columnCount=tempQuery.record().count();
                   while(tempQuery.next())
                   {
                        for(int n=0;; n++)
                       {
                          reply.append(tempQuery.value(n).toString().toUtf8()); //统一UTF8编码
                            if(n<columnCount-1)
                                reply.append('\t');
                            else break;
                       }
                        reply.append('\n');
                        if(reply.size()>=UDP_MAX_Bytes)
                            break;
                   }//while结束
                 }   // if(tempQuery.exec(strSQL))  结束
                else //如果操作数据库有误
                {
                    reply.append("ERROR: DATABASE ERROR.");
                    reply.append(tempQuery.lastError().text().toLatin1());
                }
                if(reply.size()>=UDP_MAX_Bytes)
                    break;
            }
        }
    }
    if(reply.size()<=UDP_MAX_Bytes)
        return reply;
    else
        return reply.mid(0,UDP_MAX_Bytes);
}

QByteArray GetRequestProcess::getHistoryData(QList<QByteArray> &listUriItems)
{
    QByteArray reply;
    QSqlQuery tempQuery(QSqlDatabase::database(DB_Con_Name_ClientDataProcess));

    if(listUriItems.size()!=3)
        reply="ERROR:URI is not correct.There should be 2 '/'";
    else
    {
        QByteArray nodeName,strQuery;
        nodeName=listUriItems.at(0);
        strQuery=listUriItems.at(2);
        if(!strQuery.contains("SENSORNAME=")||!strQuery.contains("DATE="))
            reply.append("ERROR:URI not correct.It should contain 'SensorName=' and 'Date='");
        else
        {
            strQuery.remove(0,6); //remove "query?"
            QByteArray dateQuery,sensorQuery;
            if(strQuery.startsWith("DATE"))
            {
                dateQuery=strQuery.split('&').at(0);
                sensorQuery=strQuery.split('&').at(1);
            }
            else if(strQuery.startsWith("SENSORNAME"))
            {
                dateQuery=strQuery.split('&').at(1);
                sensorQuery=strQuery.split('&').at(0);
            }
            QByteArray dateStart,dateEnd,sensorName;
            dateStart=dateQuery.split('=').at(1).split('-').at(0);
            dateEnd=dateQuery.split('=').at(1).split('-').at(1);
            sensorName=sensorQuery.split('=').at(1);

            QByteArray strSQL="select DateTimeStart,DateTimeEnd,AvgSensorData,MaxSensorData,MinSensorData,CountSensorData "
                    " from historysensordata hsd,typemap tm,NodeAddressMap nam where DateTimeStart>="+dateStart+" and DateTimeEnd<="+dateEnd+" and "
                    " SensorName='"+sensorName+"' and hsd.SensorID=tm.SenSorID and NodeName like '"+nodeName+"' and hsd.NodeMacAddress=nam.NodeMacAddress";

            if(tempQuery.exec(strSQL))  //如果数据库操作成功
            {
                quint8 columnCount=tempQuery.record().count();
               while(tempQuery.next())
               {
                    for(int n=0;; n++)
                   {
                      reply.append(tempQuery.value(n).toString().toUtf8()); //统一UTF8编码
                        if(n<columnCount-1)
                            reply.append('\t');
                        else break;
                   }
                    reply.append('\n');
                    if(reply.size()>=UDP_MAX_Bytes)
                        break;
               }//while结束

             }   // if(tempQuery.exec(strSQL))  结束
            else //如果操作数据库有误
            {
                reply.append("ERROR: DATABASE ERROR.");
                reply.append(tempQuery.lastError().text().toLatin1());
            }
        }
    }
    if(reply.size()<=UDP_MAX_Bytes)
        return reply;
    else
        return reply.mid(0,UDP_MAX_Bytes);
}

QByteArray GetRequestProcess::getInfo(QList<QByteArray> &listUriItems)
{
    QByteArray reply;
    QSqlQuery tempQuery(QSqlDatabase::database(DB_Con_Name_ClientDataProcess));

    if(listUriItems.size()!=4)
        reply="ERROR:URI is not correct.There should be 3 '/'";
    else
    {
        QByteArray tableName,columnName,whereClause;
        tableName=listUriItems.at(1);
        columnName=listUriItems.at(2);
        QString tempQueryStr=listUriItems.at(3);
        if(!tempQueryStr.contains("QUERY?"))
            reply="ERROR:URI not correct.It should contain 'Query?'";
        else
        {
            whereClause=tempQueryStr.split("QUERY?").at(1).toUtf8();
            whereClause.replace("_"," ");
            QByteArray strSQL="select "+columnName+" from "+tableName+" where "+whereClause;

            if(tempQuery.exec(strSQL))  //如果数据库操作成功
            {
                quint8 columnCount=tempQuery.record().count();
               while(tempQuery.next())
               {
                    for(int n=0;; n++)
                   {
                      reply.append(tempQuery.value(n).toString().toUtf8()); //统一UTF8编码
                        if(n<columnCount-1)
                            reply.append('\t');
                        else
                            break;
                   }
                    reply.append('\n');
                    if(reply.size()>=UDP_MAX_Bytes)
                        break;
               }//while结束
             }   // if(tempQuery.exec(strSQL))  结束
            else //如果操作数据库有误
            {
                reply.append("ERROR: DATABASE ERROR.");
                reply.append(tempQuery.lastError().text().toLatin1());
            }
        }
    }
        return reply.mid(0,UDP_MAX_Bytes);
}

QByteArray GetRequestProcess::getState(QList<QByteArray> &listUriItems)
{
    QByteArray reply;
    reply.append("DATA_Type:NodeSensor State\n");

    QSqlQuery tempSqlQuery(QSqlDatabase::database(DB_Con_Name_ClientDataProcess));


    if(listUriItems.size()!=3)
        reply="ERROR:URI is not correct.There should be 2 '/'";
    else
    {
        QString tempQuery=listUriItems.at(2);
        if(!tempQuery.contains("QUERY?"))
            reply="ERROR:URI not correct.It should contain 'Query?'";
        else
        {
            QByteArray baNodeNameClause=listUriItems.at(0);
            QByteArray whereClause=tempQuery.split("QUERY?").at(1).toUtf8();
            whereClause.replace("_"," ");
            QByteArray strSQL="select NodeMacAddress,NodeName,SensorID,SensorName,LastEventData "
                    " from NodeSensorView where NodeName like '"+baNodeNameClause+"' and "+whereClause;

            if(tempSqlQuery.exec(strSQL))  //如果数据库操作成功
            {
               if(tempSqlQuery.next())
               {
                   bool ok;
                   reply.append("NodeName:"+tempSqlQuery.value(1).toString().toUtf8()+"\n");
                   reply.append("NodeMac:"+QByteArray::number(
                                    tempSqlQuery.value(0).toULongLong(&ok),10)+"\n");
                   reply.append("SensorID:"+QByteArray::number(
                                    tempSqlQuery.value(2).toUInt(&ok),10)+"\n");
                   reply.append("SensorName:"+tempSqlQuery.value(3).toString().toUtf8()+"\n");
                   reply.append("Content-Type:Decimal String\n");
                   reply.append("State:"+tempSqlQuery.value(4).toString().toUtf8()+"\n");
               }
               else
                   reply="ERROR: Not Found for "+dataGramProcessing;
             }   // if(tempQuery.exec(strSQL))  结束
            else //如果操作数据库有误
            {
                qDebug()<<strSQL;

                reply="ERROR: DATABASE ERROR when querying "+dataGramProcessing+'\n';
                reply.append(tempSqlQuery.lastError().text().toLatin1());
            }
        }
    }
        return reply.mid(0,UDP_MAX_Bytes);
}
